package com.abhinav.concurrency;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class DirectorySizer extends RecursiveTask<Long> {
	private static final long serialVersionUID = 2412039806740791328L;
	private List<File> mFiles;
	private boolean mAllFiles = true;

	public DirectorySizer(List<File> files) {
		mFiles = files;
		for (File file : mFiles) {
			if (file.isDirectory()) {
				mAllFiles = false;
			}
		}
	}

	@Override
	protected Long compute() {
		if (mFiles.size() <= 4 && mAllFiles) {
			return computeTotal();
		} else {
			return forkAndJoin();
		}
	}

	private Long forkAndJoin() {
		List<File> dirsAndFiles = new ArrayList<>();
		for (File file : mFiles) {
			if (file.isFile()) {
				dirsAndFiles.add(file);
			} else {
				dirsAndFiles.addAll(Arrays.asList(file.listFiles()));
			}
		}

		int rightSize = dirsAndFiles.size() / 2;
		int leftSize = dirsAndFiles.size() - rightSize;
		List<File> leftList = dirsAndFiles.subList(0, leftSize);
		List<File> rightList = dirsAndFiles.subList(leftSize, leftSize
				+ rightSize);

		DirectorySizer d1 = new DirectorySizer(leftList);
		d1.fork();

		DirectorySizer d2 = new DirectorySizer(rightList);

		return d2.compute() + d1.join();
	}

	private Long computeTotal() {
		long length = 0;
		for (File file : mFiles) {
			length += file.length();
		}
		return length;
	}

	public static void main(String[] args) {
		String input =  "D:/Abhinav";
		List<File> files = Arrays.asList(new File(input).listFiles());
		DirectorySizer sizer = new DirectorySizer(files);
		ForkJoinPool pool = new ForkJoinPool();
		long size = pool.invoke(sizer);
		

		System.out.println(input + " is " + size/(1024*1024) + " mbytes ");
	}

}
